/***********************************************************
 * Author: 	Brandon McKune
 * E-Mail:	bmckune.cs@gmail.com
 * Date:	September 2, 2011
 * Class:	CSc 8370 - Data Security
 * Time:	1150 - 1325
 * Smstr:	Fall 2011
 */

#include "adfgvxDecipher.h"

adfgvxDecipher::adfgvxDecipher(){
	this->m_prgCipherText = NULL;
	this->m_ui64NumInfos = NULL;
	this->m_ui64TextSize = 0;
	this->m_pCMatrixHandler = new MatrixHandler();
	this->m_pCStatsHandler = new StatisticsHandler();
}

adfgvxDecipher::~adfgvxDecipher(){
	this->clearCipher();
	if(this->m_pCMatrixHandler != NULL){
		delete(this->m_pCMatrixHandler);
	}
	if(this->m_pCStatsHandler != NULL){
		delete(this->m_pCStatsHandler);
	}

	free(this->m_pSuDoubleInfo);
}

bool adfgvxDecipher::loadCipher(char* text, size_t numBytes){
	if(text == NULL){
		fprintf(stderr, "loadCipher::text->NULL");
		return false;
	}

	if(numBytes < 2){
		fprintf(stderr, "loadCipher::numBytes < 2; impossible for adfgvx");
		return false;
	}

	this->m_prgCipherText = (char*)malloc(sizeof(char)*numBytes + 1);
	if(this->m_prgCipherText == NULL){
		fprintf(stderr, "loadCipher::malloc failed.");
		return false;
	}

	this->m_ui64TextSize = numBytes;

	memcpy(this->m_prgCipherText, text, numBytes);
	this->m_prgCipherText[numBytes] = '\0';
}

void adfgvxDecipher::attemptDecription(UINT numColStart, UINT numColEnd){
	if(this->m_prgCipherText == NULL){
		fprintf(stderr, "attemptDecription::adfgvxDecipher not setup properly.");
		return;
	}

	if(numColStart > numColEnd){
		fprintf(stderr, "attemptDecription::start > end.");
		return;
	}

	if(numColStart < 1){
		fprintf(stderr, "attemptDecription:: start = 0, unacceptable.");
		return;
	}

	if(numColEnd > this->m_ui64TextSize){
		fprintf(stderr, "attemptDecription:: end > buffer size, unacceptable.");
		return;
	}

	char* temp_buffer;
	this->m_ui64NumInfos = numColEnd-numColStart;
	this->m_pSuDoubleInfo =
			(SuDoubleInfo*)malloc(sizeof(SuDoubleInfo)*this->m_ui64NumInfos);
	UINT index = 0;
	for(UINT i = numColStart; i < numColEnd; i++){
		this->m_bLoadedSuccessfully = this->m_pCMatrixHandler->loadMatrix(
						this->m_prgCipherText, this->m_ui64TextSize, i);

		if(!this->m_bLoadedSuccessfully){
			fprintf(stderr, "attemptDecription:: loadMatrix failed.");
			return;
		}
		temp_buffer = this->m_pCMatrixHandler->transposeMatrix();

		this->m_pCStatsHandler->loadCharBuffer(temp_buffer, this->m_ui64TextSize);
		this->m_pSuDoubleInfo[index].m_dValue = this->m_pCStatsHandler->getPsi(2);
		this->m_pSuDoubleInfo[index].m_ui64ColNum = i;
		free(temp_buffer);
		index++;
	}
}

void adfgvxDecipher::printResults(){
	for(UINT i = 0; i < this->m_ui64NumInfos; i++){
		printf("Psi: %f | Cols: %ld\n",
				this->m_pSuDoubleInfo[i].m_dValue, this->m_pSuDoubleInfo[i].m_ui64ColNum);
	}
}
/***********************************************************
 * Protected Functional Members
 */
void adfgvxDecipher::clearCipher(){
	if(this->m_prgCipherText != NULL){
		free(this->m_prgCipherText);
		this->m_prgCipherText = NULL;
	}

	this->m_ui64TextSize = 0;
}
